home *** CD-ROM | disk | FTP | other *** search
/ PC/CD Gamer UK 120 / CD Gamer Issue 120 (March 2003) (Disc 2).ISO / mods / Q2_Codered / codeRED1_0.exe / Data1.cab / snd_dma.c < prev    next >
Encoding:
C/C++ Source or Header  |  2002-08-13  |  25.2 KB  |  1,215 lines

  1. /*
  2. Copyright (C) 1997-2001 Id Software, Inc.
  3.  
  4. This program is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU General Public License
  6. as published by the Free Software Foundation; either version 2
  7. of the License, or (at your option) any later version.
  8.  
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
  12.  
  13. See the GNU General Public License for more details.
  14.  
  15. You should have received a copy of the GNU General Public License
  16. along with this program; if not, write to the Free Software
  17. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  18.  
  19. */
  20. // snd_dma.c -- main control for any streaming sound output device
  21.  
  22. #include "client.h"
  23. #include "snd_loc.h"
  24.  
  25. void S_Play(void);
  26. void S_SoundList(void);
  27. void S_Update_();
  28. void S_StopAllSounds(void);
  29.  
  30.  
  31. // =======================================================================
  32. // Internal sound data & structures
  33. // =======================================================================
  34.  
  35. // only begin attenuating sound volumes when outside the FULLVOLUME range
  36. #define        SOUND_FULLVOLUME    80
  37.  
  38. #define        SOUND_LOOPATTENUATE    0.003
  39.  
  40. int            s_registration_sequence;
  41.  
  42. channel_t   channels[MAX_CHANNELS];
  43.  
  44. qboolean    snd_initialized = false;
  45. int            sound_started=0;
  46.  
  47. dma_t        dma;
  48.  
  49. vec3_t        listener_origin;
  50. vec3_t        listener_forward;
  51. vec3_t        listener_right;
  52. vec3_t        listener_up;
  53.  
  54. qboolean    s_registering;
  55.  
  56. int            soundtime;        // sample PAIRS
  57. int           paintedtime;     // sample PAIRS
  58.  
  59. // during registration it is possible to have more sounds
  60. // than could actually be referenced during gameplay,
  61. // because we don't want to free anything until we are
  62. // sure we won't need it.
  63. #define        MAX_SFX        (MAX_SOUNDS*2)
  64. sfx_t        known_sfx[MAX_SFX];
  65. int            num_sfx;
  66.  
  67. #define        MAX_PLAYSOUNDS    128
  68. playsound_t    s_playsounds[MAX_PLAYSOUNDS];
  69. playsound_t    s_freeplays;
  70. playsound_t    s_pendingplays;
  71.  
  72. int            s_beginofs;
  73.  
  74. cvar_t        *s_volume;
  75. cvar_t        *s_testsound;
  76. cvar_t        *s_loadas8bit;
  77. cvar_t        *s_khz;
  78. cvar_t        *s_show;
  79. cvar_t        *s_mixahead;
  80. cvar_t        *s_primary;
  81.  
  82.  
  83. int        s_rawend;
  84. portable_samplepair_t    s_rawsamples[MAX_RAW_SAMPLES];
  85.  
  86.  
  87. // ====================================================================
  88. // User-setable variables
  89. // ====================================================================
  90.  
  91.  
  92. void S_SoundInfo_f(void)
  93. {
  94.     if (!sound_started)
  95.     {
  96.         Com_Printf ("sound system not started\n");
  97.         return;
  98.     }
  99.     
  100.     Com_Printf("%5d stereo\n", dma.channels - 1);
  101.     Com_Printf("%5d samples\n", dma.samples);
  102.     Com_Printf("%5d samplepos\n", dma.samplepos);
  103.     Com_Printf("%5d samplebits\n", dma.samplebits);
  104.     Com_Printf("%5d submission_chunk\n", dma.submission_chunk);
  105.     Com_Printf("%5d speed\n", dma.speed);
  106.     Com_Printf("0x%x dma buffer\n", dma.buffer);
  107. }
  108.  
  109.  
  110.  
  111. /*
  112. ================
  113. S_Init
  114. ================
  115. */
  116. void S_Init (void)
  117. {
  118.     cvar_t    *cv;
  119.  
  120.     Com_Printf("\n------- sound initialization -------\n");
  121.  
  122.     cv = Cvar_Get ("s_initsound", "1", 0);
  123.     if (!cv->value)
  124.         Com_Printf ("not initializing.\n");
  125.     else
  126.     {
  127.         s_volume = Cvar_Get ("s_volume", "0.7", CVAR_ARCHIVE);
  128.         s_khz = Cvar_Get ("s_khz", "11", CVAR_ARCHIVE);
  129.         s_loadas8bit = Cvar_Get ("s_loadas8bit", "1", CVAR_ARCHIVE);
  130.         s_mixahead = Cvar_Get ("s_mixahead", "0.2", CVAR_ARCHIVE);
  131.         s_show = Cvar_Get ("s_show", "0", 0);
  132.         s_testsound = Cvar_Get ("s_testsound", "0", 0);
  133.         s_primary = Cvar_Get ("s_primary", "0", CVAR_ARCHIVE);    // win32 specific
  134.  
  135.         Cmd_AddCommand("play", S_Play);
  136.         Cmd_AddCommand("stopsound", S_StopAllSounds);
  137.         Cmd_AddCommand("soundlist", S_SoundList);
  138.         Cmd_AddCommand("soundinfo", S_SoundInfo_f);
  139.  
  140.         if (!SNDDMA_Init())
  141.             return;
  142.  
  143.         S_InitScaletable ();
  144.  
  145.         sound_started = 1;
  146.         num_sfx = 0;
  147.  
  148.         soundtime = 0;
  149.         paintedtime = 0;
  150.  
  151.         Com_Printf ("sound sampling rate: %i\n", dma.speed);
  152.  
  153.         S_StopAllSounds ();
  154.     }
  155.  
  156.     Com_Printf("------------------------------------\n");
  157. }
  158.  
  159.  
  160. // =======================================================================
  161. // Shutdown sound engine
  162. // =======================================================================
  163.  
  164. void S_Shutdown(void)
  165. {
  166.     int        i;
  167.     sfx_t    *sfx;
  168.  
  169.     if (!sound_started)
  170.         return;
  171.  
  172.     SNDDMA_Shutdown();
  173.  
  174.     sound_started = 0;
  175.  
  176.     Cmd_RemoveCommand("play");
  177.     Cmd_RemoveCommand("stopsound");
  178.     Cmd_RemoveCommand("soundlist");
  179.     Cmd_RemoveCommand("soundinfo");
  180.  
  181.     // free all sounds
  182.     for (i=0, sfx=known_sfx ; i < num_sfx ; i++,sfx++)
  183.     {
  184.         if (!sfx->name[0])
  185.             continue;
  186.         if (sfx->cache)
  187.             Z_Free (sfx->cache);
  188.         memset (sfx, 0, sizeof(*sfx));
  189.     }
  190.  
  191.     num_sfx = 0;
  192. }
  193.  
  194.  
  195. // =======================================================================
  196. // Load a sound
  197. // =======================================================================
  198.  
  199. /*
  200. ==================
  201. S_FindName
  202.  
  203. ==================
  204. */
  205. sfx_t *S_FindName (char *name, qboolean create)
  206. {
  207.     int        i;
  208.     sfx_t    *sfx;
  209.  
  210.     if (!name)
  211.         Com_Error (ERR_FATAL, "S_FindName: NULL\n");
  212.     if (!name[0])
  213.         Com_Error (ERR_FATAL, "S_FindName: empty name\n");
  214.  
  215.     if (strlen(name) >= MAX_QPATH)
  216.         Com_Error (ERR_FATAL, "Sound name too long: %s", name);
  217.  
  218.     // see if already loaded
  219.     for (i=0 ; i < num_sfx ; i++)
  220.         if (!strcmp(known_sfx[i].name, name))
  221.         {
  222.             return &known_sfx[i];
  223.         }
  224.  
  225.     if (!create)
  226.         return NULL;
  227.  
  228.     // find a free sfx
  229.     for (i=0 ; i < num_sfx ; i++)
  230.         if (!known_sfx[i].name[0])
  231. //            registration_sequence < s_registration_sequence)
  232.             break;
  233.  
  234.     if (i == num_sfx)
  235.     {
  236.         if (num_sfx == MAX_SFX)
  237.             Com_Error (ERR_FATAL, "S_FindName: out of sfx_t");
  238.         num_sfx++;
  239.     }
  240.     
  241.     sfx = &known_sfx[i];
  242.     memset (sfx, 0, sizeof(*sfx));
  243.     strcpy (sfx->name, name);
  244.     sfx->registration_sequence = s_registration_sequence;
  245.     
  246.     return sfx;
  247. }
  248.  
  249.  
  250. /*
  251. ==================
  252. S_AliasName
  253.  
  254. ==================
  255. */
  256. sfx_t *S_AliasName (char *aliasname, char *truename)
  257. {
  258.     sfx_t    *sfx;
  259.     char    *s;
  260.     int        i;
  261.  
  262.     s = Z_Malloc (MAX_QPATH);
  263.     strcpy (s, truename);
  264.  
  265.     // find a free sfx
  266.     for (i=0 ; i < num_sfx ; i++)
  267.         if (!known_sfx[i].name[0])
  268.             break;
  269.  
  270.     if (i == num_sfx)
  271.     {
  272.         if (num_sfx == MAX_SFX)
  273.             Com_Error (ERR_FATAL, "S_FindName: out of sfx_t");
  274.         num_sfx++;
  275.     }
  276.     
  277.     sfx = &known_sfx[i];
  278.     memset (sfx, 0, sizeof(*sfx));
  279.     strcpy (sfx->name, aliasname);
  280.     sfx->registration_sequence = s_registration_sequence;
  281.     sfx->truename = s;
  282.  
  283.     return sfx;
  284. }
  285.  
  286.  
  287. /*
  288. =====================
  289. S_BeginRegistration
  290.  
  291. =====================
  292. */
  293. void S_BeginRegistration (void)
  294. {
  295.     s_registration_sequence++;
  296.     s_registering = true;
  297. }
  298.  
  299. /*
  300. ==================
  301. S_RegisterSound
  302.  
  303. ==================
  304. */
  305. sfx_t *S_RegisterSound (char *name)
  306. {
  307.     sfx_t    *sfx;
  308.  
  309.     if (!sound_started)
  310.         return NULL;
  311.  
  312.     sfx = S_FindName (name, true);
  313.     sfx->registration_sequence = s_registration_sequence;
  314.  
  315.     if (!s_registering)
  316.         S_LoadSound (sfx);
  317.  
  318.     return sfx;
  319. }
  320.  
  321.  
  322. /*
  323. =====================
  324. S_EndRegistration
  325.  
  326. =====================
  327. */
  328. void S_EndRegistration (void)
  329. {
  330.     int        i;
  331.     sfx_t    *sfx;
  332.     int        size;
  333.  
  334.     // free any sounds not from this registration sequence
  335.     for (i=0, sfx=known_sfx ; i < num_sfx ; i++,sfx++)
  336.     {
  337.         if (!sfx->name[0])
  338.             continue;
  339.         if (sfx->registration_sequence != s_registration_sequence)
  340.         {    // don't need this sound
  341.             if (sfx->cache)    // it is possible to have a leftover
  342.                 Z_Free (sfx->cache);    // from a server that didn't finish loading
  343.             memset (sfx, 0, sizeof(*sfx));
  344.         }
  345.         else
  346.         {    // make sure it is paged in
  347.             if (sfx->cache)
  348.             {
  349.                 size = sfx->cache->length*sfx->cache->width;
  350.                 Com_PageInMemory ((byte *)sfx->cache, size);
  351.             }
  352.         }
  353.  
  354.     }
  355.  
  356.     // load everything in
  357.     for (i=0, sfx=known_sfx ; i < num_sfx ; i++,sfx++)
  358.     {
  359.         if (!sfx->name[0])
  360.             continue;
  361.         S_LoadSound (sfx);
  362.     }
  363.  
  364.     s_registering = false;
  365. }
  366.  
  367.  
  368. //=============================================================================
  369.  
  370. /*
  371. =================
  372. S_PickChannel
  373. =================
  374. */
  375. channel_t *S_PickChannel(int entnum, int entchannel)
  376. {
  377.     int            ch_idx;
  378.     int            first_to_die;
  379.     int            life_left;
  380.     channel_t    *ch;
  381.  
  382.     if (entchannel<0)
  383.         Com_Error (ERR_DROP, "S_PickChannel: entchannel<0");
  384.  
  385. // Check for replacement sound, or find the best one to replace
  386.     first_to_die = -1;
  387.     life_left = 0x7fffffff;
  388.     for (ch_idx=0 ; ch_idx < MAX_CHANNELS ; ch_idx++)
  389.     {
  390.         if (entchannel != 0        // channel 0 never overrides
  391.         && channels[ch_idx].entnum == entnum
  392.         && channels[ch_idx].entchannel == entchannel)
  393.         {    // always override sound from same entity
  394.             first_to_die = ch_idx;
  395.             break;
  396.         }
  397.  
  398.         // don't let monster sounds override player sounds
  399.         if (channels[ch_idx].entnum == cl.playernum+1 && entnum != cl.playernum+1 && channels[ch_idx].sfx)
  400.             continue;
  401.  
  402.         if (channels[ch_idx].end - paintedtime < life_left)
  403.         {
  404.             life_left = channels[ch_idx].end - paintedtime;
  405.             first_to_die = ch_idx;
  406.         }
  407.    }
  408.  
  409.     if (first_to_die == -1)
  410.         return NULL;
  411.  
  412.     ch = &channels[first_to_die];
  413.     memset (ch, 0, sizeof(*ch));
  414.  
  415.     return ch;
  416. }       
  417.  
  418. /*
  419. =================
  420. S_SpatializeOrigin
  421.  
  422. Used for spatializing channels and autosounds
  423. =================
  424. */
  425. void S_SpatializeOrigin (vec3_t origin, float master_vol, float dist_mult, int *left_vol, int *right_vol)
  426. {
  427.     vec_t        dot;
  428.     vec_t        dist;
  429.     vec_t        lscale, rscale, scale;
  430.     vec3_t        source_vec;
  431.  
  432.     if (cls.state != ca_active)
  433.     {
  434.         *left_vol = *right_vol = 255;
  435.         return;
  436.     }
  437.  
  438. // calculate stereo seperation and distance attenuation
  439.     VectorSubtract(origin, listener_origin, source_vec);
  440.  
  441.     dist = VectorNormalize(source_vec);
  442.     dist -= SOUND_FULLVOLUME;
  443.     if (dist < 0)
  444.         dist = 0;            // close enough to be at full volume
  445.     dist *= dist_mult;        // different attenuation levels
  446.     
  447.     dot = DotProduct(listener_right, source_vec);
  448.  
  449.     if (dma.channels == 1 || !dist_mult)
  450.     { // no attenuation = no spatialization
  451.         rscale = 1.0;
  452.         lscale = 1.0;
  453.     }
  454.     else
  455.     {
  456.         rscale = 0.5 * (1.0 + dot);
  457.         lscale = 0.5*(1.0 - dot);
  458.     }
  459.  
  460.     // add in distance effect
  461.     scale = (1.0 - dist) * rscale;
  462.     *right_vol = (int) (master_vol * scale);
  463.     if (*right_vol < 0)
  464.         *right_vol = 0;
  465.  
  466.     scale = (1.0 - dist) * lscale;
  467.     *left_vol = (int) (master_vol * scale);
  468.     if (*left_vol < 0)
  469.         *left_vol = 0;
  470. }
  471.  
  472. /*
  473. =================
  474. S_Spatialize
  475. =================
  476. */
  477. void S_Spatialize(channel_t *ch)
  478. {
  479.     vec3_t        origin;
  480.  
  481.     // anything coming from the view entity will always be full volume
  482.     if (ch->entnum == cl.playernum+1)
  483.     {
  484.         ch->leftvol = ch->master_vol;
  485.         ch->rightvol = ch->master_vol;
  486.         return;
  487.     }
  488.  
  489.     if (ch->fixed_origin)
  490.     {
  491.         VectorCopy (ch->origin, origin);
  492.     }
  493.     else
  494.         CL_GetEntitySoundOrigin (ch->entnum, origin);
  495.  
  496.     S_SpatializeOrigin (origin, ch->master_vol, ch->dist_mult, &ch->leftvol, &ch->rightvol);
  497. }           
  498.  
  499.  
  500. /*
  501. =================
  502. S_AllocPlaysound
  503. =================
  504. */
  505. playsound_t *S_AllocPlaysound (void)
  506. {
  507.     playsound_t    *ps;
  508.  
  509.     ps = s_freeplays.next;
  510.     if (ps == &s_freeplays)
  511.         return NULL;        // no free playsounds
  512.  
  513.     // unlink from freelist
  514.     ps->prev->next = ps->next;
  515.     ps->next->prev = ps->prev;
  516.     
  517.     return ps;
  518. }
  519.  
  520.  
  521. /*
  522. =================
  523. S_FreePlaysound
  524. =================
  525. */
  526. void S_FreePlaysound (playsound_t *ps)
  527. {
  528.     // unlink from channel
  529.     ps->prev->next = ps->next;
  530.     ps->next->prev = ps->prev;
  531.  
  532.     // add to free list
  533.     ps->next = s_freeplays.next;
  534.     s_freeplays.next->prev = ps;
  535.     ps->prev = &s_freeplays;
  536.     s_freeplays.next = ps;
  537. }
  538.  
  539.  
  540.  
  541. /*
  542. ===============
  543. S_IssuePlaysound
  544.  
  545. Take the next playsound and begin it on the channel
  546. This is never called directly by S_Play*, but only
  547. by the update loop.
  548. ===============
  549. */
  550. void S_IssuePlaysound (playsound_t *ps)
  551. {
  552.     channel_t    *ch;
  553.     sfxcache_t    *sc;
  554.  
  555.     if (s_show->value)
  556.         Com_Printf ("Issue %i\n", ps->begin);
  557.     // pick a channel to play on
  558.     ch = S_PickChannel(ps->entnum, ps->entchannel);
  559.     if (!ch)
  560.     {
  561.         S_FreePlaysound (ps);
  562.         return;
  563.     }
  564.  
  565.     // spatialize
  566.     if (ps->attenuation == ATTN_STATIC)
  567.         ch->dist_mult = ps->attenuation * 0.001;
  568.     else
  569.         ch->dist_mult = ps->attenuation * 0.0005;
  570.     ch->master_vol = ps->volume;
  571.     ch->entnum = ps->entnum;
  572.     ch->entchannel = ps->entchannel;
  573.     ch->sfx = ps->sfx;
  574.     VectorCopy (ps->origin, ch->origin);
  575.     ch->fixed_origin = ps->fixed_origin;
  576.  
  577.     S_Spatialize(ch);
  578.  
  579.     ch->pos = 0;
  580.     sc = S_LoadSound (ch->sfx);
  581.     ch->end = paintedtime + sc->length;
  582.  
  583.     // free the playsound
  584.     S_FreePlaysound (ps);
  585. }
  586.  
  587. struct sfx_s *S_RegisterSexedSound (entity_state_t *ent, char *base)
  588. {
  589.     int                n;
  590.     char            *p;
  591.     struct sfx_s    *sfx;
  592.     FILE            *f;
  593.     char            model[MAX_QPATH];
  594.     char            sexedFilename[MAX_QPATH];
  595.     char            maleFilename[MAX_QPATH];
  596.  
  597.     // determine what model the client is using
  598.     model[0] = 0;
  599.     n = CS_PLAYERSKINS + ent->number - 1;
  600.     if (cl.configstrings[n][0])
  601.     {
  602.         p = strchr(cl.configstrings[n], '\\');
  603.         if (p)
  604.         {
  605.             p += 1;
  606.             strcpy(model, p);
  607.             p = strchr(model, '/');
  608.             if (p)
  609.                 *p = 0;
  610.         }
  611.     }
  612.     // if we can't figure it out, they're male
  613.     if (!model[0])
  614.         strcpy(model, "male");
  615.  
  616.     // see if we already know of the model specific sound
  617.     Com_sprintf (sexedFilename, sizeof(sexedFilename), "#players/%s/%s", model, base+1);
  618.     sfx = S_FindName (sexedFilename, false);
  619.  
  620.     if (!sfx)
  621.     {
  622.         // no, so see if it exists
  623.         FS_FOpenFile (&sexedFilename[1], &f);
  624.         if (f)
  625.         {
  626.             // yes, close the file and register it
  627.             FS_FCloseFile (f);
  628.             sfx = S_RegisterSound (sexedFilename);
  629.         }
  630.         else
  631.         {
  632.             // no, revert to the male sound in the pak0.pak
  633.             Com_sprintf (maleFilename, sizeof(maleFilename), "player/%s/%s", "male", base+1);
  634.             sfx = S_AliasName (sexedFilename, maleFilename);
  635.         }
  636.     }
  637.  
  638.     return sfx;
  639. }
  640.  
  641.  
  642. // =======================================================================
  643. // Start a sound effect
  644. // =======================================================================
  645.  
  646. /*
  647. ====================
  648. S_StartSound
  649.  
  650. Validates the parms and ques the sound up
  651. if pos is NULL, the sound will be dynamically sourced from the entity
  652. Entchannel 0 will never override a playing sound
  653. ====================
  654. */
  655. void S_StartSound(vec3_t origin, int entnum, int entchannel, sfx_t *sfx, float fvol, float attenuation, float timeofs)
  656. {
  657.     sfxcache_t    *sc;
  658.     int            vol;
  659.     playsound_t    *ps, *sort;
  660.     int            start;
  661.  
  662.     if (!sound_started)
  663.         return;
  664.  
  665.     if (!sfx)
  666.         return;
  667.  
  668.     if (sfx->name[0] == '*')
  669.         sfx = S_RegisterSexedSound(&cl_entities[entnum].current, sfx->name);
  670.  
  671.     // make sure the sound is loaded
  672.     sc = S_LoadSound (sfx);
  673.     if (!sc)
  674.         return;        // couldn't load the sound's data
  675.  
  676.     vol = fvol*255;
  677.  
  678.     // make the playsound_t
  679.     ps = S_AllocPlaysound ();
  680.     if (!ps)
  681.         return;
  682.  
  683.     if (origin)
  684.     {
  685.         VectorCopy (origin, ps->origin);
  686.         ps->fixed_origin = true;
  687.     }
  688.     else
  689.         ps->fixed_origin = false;
  690.  
  691.     ps->entnum = entnum;
  692.     ps->entchannel = entchannel;
  693.     ps->attenuation = attenuation;
  694.     ps->volume = vol;
  695.     ps->sfx = sfx;
  696.  
  697.     // drift s_beginofs
  698.     start = cl.frame.servertime * 0.001 * dma.speed + s_beginofs;
  699.     if (start < paintedtime)
  700.     {
  701.         start = paintedtime;
  702.         s_beginofs = start - (cl.frame.servertime * 0.001 * dma.speed);
  703.     }
  704.     else if (start > paintedtime + 0.3 * dma.speed)
  705.     {
  706.         start = paintedtime + 0.1 * dma.speed;
  707.         s_beginofs = start - (cl.frame.servertime * 0.001 * dma.speed);
  708.     }
  709.     else
  710.     {
  711.         s_beginofs-=10;
  712.     }
  713.  
  714.     if (!timeofs)
  715.         ps->begin = paintedtime;
  716.     else
  717.         ps->begin = start + timeofs * dma.speed;
  718.  
  719.     // sort into the pending sound list
  720.     for (sort = s_pendingplays.next ; 
  721.         sort != &s_pendingplays && sort->begin < ps->begin ;
  722.         sort = sort->next)
  723.             ;
  724.  
  725.     ps->next = sort;
  726.     ps->prev = sort->prev;
  727.  
  728.     ps->next->prev = ps;
  729.     ps->prev->next = ps;
  730. }
  731.  
  732.  
  733. /*
  734. ==================
  735. S_StartLocalSound
  736. ==================
  737. */
  738. void S_StartLocalSound (char *sound)
  739. {
  740.     sfx_t    *sfx;
  741.  
  742.     if (!sound_started)
  743.         return;
  744.         
  745.     sfx = S_RegisterSound (sound);
  746.     if (!sfx)
  747.     {
  748.         Com_Printf ("S_StartLocalSound: can't cache %s\n", sound);
  749.         return;
  750.     }
  751.     S_StartSound (NULL, cl.playernum+1, 0, sfx, 1, 1, 0);
  752. }
  753.  
  754.  
  755. /*
  756. ==================
  757. S_ClearBuffer
  758. ==================
  759. */
  760. void S_ClearBuffer (void)
  761. {
  762.     int        clear;
  763.         
  764.     if (!sound_started)
  765.         return;
  766.  
  767.     s_rawend = 0;
  768.  
  769.     if (dma.samplebits == 8)
  770.         clear = 0x80;
  771.     else
  772.         clear = 0;
  773.  
  774.     SNDDMA_BeginPainting ();
  775.     if (dma.buffer)
  776.         memset(dma.buffer, clear, dma.samples * dma.samplebits/8);
  777.     SNDDMA_Submit ();
  778. }
  779.  
  780. /*
  781. ==================
  782. S_StopAllSounds
  783. ==================
  784. */
  785. void S_StopAllSounds(void)
  786. {
  787.     int        i;
  788.  
  789.     if (!sound_started)
  790.         return;
  791.  
  792.     // clear all the playsounds
  793.     memset(s_playsounds, 0, sizeof(s_playsounds));
  794.     s_freeplays.next = s_freeplays.prev = &s_freeplays;
  795.     s_pendingplays.next = s_pendingplays.prev = &s_pendingplays;
  796.  
  797.     for (i=0 ; i<MAX_PLAYSOUNDS ; i++)
  798.     {
  799.         s_playsounds[i].prev = &s_freeplays;
  800.         s_playsounds[i].next = s_freeplays.next;
  801.         s_playsounds[i].prev->next = &s_playsounds[i];
  802.         s_playsounds[i].next->prev = &s_playsounds[i];
  803.     }
  804.  
  805.     // clear all the channels
  806.     memset(channels, 0, sizeof(channels));
  807.  
  808.     S_ClearBuffer ();
  809. }
  810.  
  811. /*
  812. ==================
  813. S_AddLoopSounds
  814.  
  815. Entities with a ->sound field will generated looped sounds
  816. that are automatically started, stopped, and merged together
  817. as the entities are sent to the client
  818. ==================
  819. */
  820. void S_AddLoopSounds (void)
  821. {
  822.     int            i, j;
  823.     int            sounds[MAX_EDICTS];
  824.     int            left, right, left_total, right_total;
  825.     channel_t    *ch;
  826.     sfx_t        *sfx;
  827.     sfxcache_t    *sc;
  828.     int            num;
  829.     entity_state_t    *ent;
  830.  
  831.     if (cl_paused->value)
  832.         return;
  833.  
  834.     if (cls.state != ca_active)
  835.         return;
  836.  
  837.     if (!cl.sound_prepped)
  838.         return;
  839.  
  840.     for (i=0 ; i<cl.frame.num_entities ; i++)
  841.     {
  842.         num = (cl.frame.parse_entities + i)&(MAX_PARSE_ENTITIES-1);
  843.         ent = &cl_parse_entities[num];
  844.         sounds[i] = ent->sound;
  845.     }
  846.  
  847.     for (i=0 ; i<cl.frame.num_entities ; i++)
  848.     {
  849.         if (!sounds[i])
  850.             continue;
  851.  
  852.         sfx = cl.sound_precache[sounds[i]];
  853.         if (!sfx)
  854.             continue;        // bad sound effect
  855.         sc = sfx->cache;
  856.         if (!sc)
  857.             continue;
  858.  
  859.         num = (cl.frame.parse_entities + i)&(MAX_PARSE_ENTITIES-1);
  860.         ent = &cl_parse_entities[num];
  861.  
  862.         // find the total contribution of all sounds of this type
  863.         S_SpatializeOrigin (ent->origin, 255.0, SOUND_LOOPATTENUATE,
  864.             &left_total, &right_total);
  865.         for (j=i+1 ; j<cl.frame.num_entities ; j++)
  866.         {
  867.             if (sounds[j] != sounds[i])
  868.                 continue;
  869.             sounds[j] = 0;    // don't check this again later
  870.  
  871.             num = (cl.frame.parse_entities + j)&(MAX_PARSE_ENTITIES-1);
  872.             ent = &cl_parse_entities[num];
  873.  
  874.             S_SpatializeOrigin (ent->origin, 255.0, SOUND_LOOPATTENUATE, 
  875.                 &left, &right);
  876.             left_total += left;
  877.             right_total += right;
  878.         }
  879.  
  880.         if (left_total == 0 && right_total == 0)
  881.             continue;        // not audible
  882.  
  883.         // allocate a channel
  884.         ch = S_PickChannel(0, 0);
  885.         if (!ch)
  886.             return;
  887.  
  888.         if (left_total > 255)
  889.             left_total = 255;
  890.         if (right_total > 255)
  891.             right_total = 255;
  892.         ch->leftvol = left_total;
  893.         ch->rightvol = right_total;
  894.         ch->autosound = true;    // remove next frame
  895.         ch->sfx = sfx;
  896.         ch->pos = paintedtime % sc->length;
  897.         ch->end = paintedtime + sc->length - ch->pos;
  898.     }
  899. }
  900.  
  901. //=============================================================================
  902.  
  903. /*
  904. ============
  905. S_RawSamples
  906.  
  907. Cinematic streaming and voice over network
  908. ============
  909. */
  910. void S_RawSamples (int samples, int rate, int width, int channels, byte *data)
  911. {
  912.     int        i;
  913.     int        src, dst;
  914.     float    scale;
  915.  
  916.     if (!sound_started)
  917.         return;
  918.  
  919.     if (s_rawend < paintedtime)
  920.         s_rawend = paintedtime;
  921.     scale = (float)rate / dma.speed;
  922.  
  923. //Com_Printf ("%i < %i < %i\n", soundtime, paintedtime, s_rawend);
  924.     if (channels == 2 && width == 2)
  925.     {
  926.         if (scale == 1.0)
  927.         {    // optimized case
  928.             for (i=0 ; i<samples ; i++)
  929.             {
  930.                 dst = s_rawend&(MAX_RAW_SAMPLES-1);
  931.                 s_rawend++;
  932.                 s_rawsamples[dst].left =
  933.                     LittleShort(((short *)data)[i*2]) << 8;
  934.                 s_rawsamples[dst].right =
  935.                     LittleShort(((short *)data)[i*2+1]) << 8;
  936.             }
  937.         }
  938.         else
  939.         {
  940.             for (i=0 ; ; i++)
  941.             {
  942.                 src = i*scale;
  943.                 if (src >= samples)
  944.                     break;
  945.                 dst = s_rawend&(MAX_RAW_SAMPLES-1);
  946.                 s_rawend++;
  947.                 s_rawsamples[dst].left =
  948.                     LittleShort(((short *)data)[src*2]) << 8;
  949.                 s_rawsamples[dst].right =
  950.                     LittleShort(((short *)data)[src*2+1]) << 8;
  951.             }
  952.         }
  953.     }
  954.     else if (channels == 1 && width == 2)
  955.     {
  956.         for (i=0 ; ; i++)
  957.         {
  958.             src = i*scale;
  959.             if (src >= samples)
  960.                 break;
  961.             dst = s_rawend&(MAX_RAW_SAMPLES-1);
  962.             s_rawend++;
  963.             s_rawsamples[dst].left =
  964.                 LittleShort(((short *)data)[src]) << 8;
  965.             s_rawsamples[dst].right =
  966.                 LittleShort(((short *)data)[src]) << 8;
  967.         }
  968.     }
  969.     else if (channels == 2 && width == 1)
  970.     {
  971.         for (i=0 ; ; i++)
  972.         {
  973.             src = i*scale;
  974.             if (src >= samples)
  975.                 break;
  976.             dst = s_rawend&(MAX_RAW_SAMPLES-1);
  977.             s_rawend++;
  978.             s_rawsamples[dst].left =
  979.                 ((char *)data)[src*2] << 16;
  980.             s_rawsamples[dst].right =
  981.                 ((char *)data)[src*2+1] << 16;
  982.         }
  983.     }
  984.     else if (channels == 1 && width == 1)
  985.     {
  986.         for (i=0 ; ; i++)
  987.         {
  988.             src = i*scale;
  989.             if (src >= samples)
  990.                 break;
  991.             dst = s_rawend&(MAX_RAW_SAMPLES-1);
  992.             s_rawend++;
  993.             s_rawsamples[dst].left =
  994.                 (((byte *)data)[src]-128) << 16;
  995.             s_rawsamples[dst].right = (((byte *)data)[src]-128) << 16;
  996.         }
  997.     }
  998. }
  999.  
  1000. //=============================================================================
  1001.  
  1002. /*
  1003. ============
  1004. S_Update
  1005.  
  1006. Called once each time through the main loop
  1007. ============
  1008. */
  1009. void S_Update(vec3_t origin, vec3_t forward, vec3_t right, vec3_t up)
  1010. {
  1011.     int            i;
  1012.     int            total;
  1013.     channel_t    *ch;
  1014.     channel_t    *combine;
  1015.  
  1016.     if (!sound_started)
  1017.         return;
  1018.  
  1019.     // if the laoding plaque is up, clear everything
  1020.     // out to make sure we aren't looping a dirty
  1021.     // dma buffer while loading
  1022.     if (cls.disable_screen)
  1023.     {
  1024.         S_ClearBuffer ();
  1025.         return;
  1026.     }
  1027.  
  1028.     // rebuild scale tables if volume is modified
  1029.     if (s_volume->modified)
  1030.         S_InitScaletable ();
  1031.  
  1032.     VectorCopy(origin, listener_origin);
  1033.     VectorCopy(forward, listener_forward);
  1034.     VectorCopy(right, listener_right);
  1035.     VectorCopy(up, listener_up);
  1036.  
  1037.     combine = NULL;
  1038.  
  1039.     // update spatialization for dynamic sounds    
  1040.     ch = channels;
  1041.     for (i=0 ; i<MAX_CHANNELS; i++, ch++)
  1042.     {
  1043.         if (!ch->sfx)
  1044.             continue;
  1045.         if (ch->autosound)
  1046.         {    // autosounds are regenerated fresh each frame
  1047.             memset (ch, 0, sizeof(*ch));
  1048.             continue;
  1049.         }
  1050.         S_Spatialize(ch);         // respatialize channel
  1051.         if (!ch->leftvol && !ch->rightvol)
  1052.         {
  1053.             memset (ch, 0, sizeof(*ch));
  1054.             continue;
  1055.         }
  1056.     }
  1057.  
  1058.     // add loopsounds
  1059.     S_AddLoopSounds ();
  1060.  
  1061.     //
  1062.     // debugging output
  1063.     //
  1064.     if (s_show->value)
  1065.     {
  1066.         total = 0;
  1067.         ch = channels;
  1068.         for (i=0 ; i<MAX_CHANNELS; i++, ch++)
  1069.             if (ch->sfx && (ch->leftvol || ch->rightvol) )
  1070.             {
  1071.                 Com_Printf ("%3i %3i %s\n", ch->leftvol, ch->rightvol, ch->sfx->name);
  1072.                 total++;
  1073.             }
  1074.         
  1075.         Com_Printf ("----(%i)---- painted: %i\n", total, paintedtime);
  1076.     }
  1077.  
  1078. // mix some sound
  1079.     S_Update_();
  1080. }
  1081.  
  1082. void GetSoundtime(void)
  1083. {
  1084.     int        samplepos;
  1085.     static    int        buffers;
  1086.     static    int        oldsamplepos;
  1087.     int        fullsamples;
  1088.     
  1089.     fullsamples = dma.samples / dma.channels;
  1090.  
  1091. // it is possible to miscount buffers if it has wrapped twice between
  1092. // calls to S_Update.  Oh well.
  1093.     samplepos = SNDDMA_GetDMAPos();
  1094.  
  1095.     if (samplepos < oldsamplepos)
  1096.     {
  1097.         buffers++;                    // buffer wrapped
  1098.         
  1099.         if (paintedtime > 0x40000000)
  1100.         {    // time to chop things off to avoid 32 bit limits
  1101.             buffers = 0;
  1102.             paintedtime = fullsamples;
  1103.             S_StopAllSounds ();
  1104.         }
  1105.     }
  1106.     oldsamplepos = samplepos;
  1107.  
  1108.     soundtime = buffers*fullsamples + samplepos/dma.channels;
  1109. }
  1110.  
  1111.  
  1112. void S_Update_(void)
  1113. {
  1114.     unsigned        endtime;
  1115.     int                samps;
  1116.  
  1117.     if (!sound_started)
  1118.         return;
  1119.  
  1120.     SNDDMA_BeginPainting ();
  1121.  
  1122.     if (!dma.buffer)
  1123.         return;
  1124.  
  1125. // Updates DMA time
  1126.     GetSoundtime();
  1127.  
  1128. // check to make sure that we haven't overshot
  1129.     if (paintedtime < soundtime)
  1130.     {
  1131.         Com_DPrintf ("S_Update_ : overflow\n");
  1132.         paintedtime = soundtime;
  1133.     }
  1134.  
  1135. // mix ahead of current position
  1136.     endtime = soundtime + s_mixahead->value * dma.speed;
  1137. //endtime = (soundtime + 4096) & ~4095;
  1138.  
  1139.     // mix to an even submission block size
  1140.     endtime = (endtime + dma.submission_chunk-1)
  1141.         & ~(dma.submission_chunk-1);
  1142.     samps = dma.samples >> (dma.channels-1);
  1143.     if (endtime - soundtime > samps)
  1144.         endtime = soundtime + samps;
  1145.  
  1146.     S_PaintChannels (endtime);
  1147.  
  1148.     SNDDMA_Submit ();
  1149. }
  1150.  
  1151. /*
  1152. ===============================================================================
  1153.  
  1154. console functions
  1155.  
  1156. ===============================================================================
  1157. */
  1158.  
  1159. void S_Play(void)
  1160. {
  1161.     int     i;
  1162.     char name[256];
  1163.     sfx_t    *sfx;
  1164.     
  1165.     i = 1;
  1166.     while (i<Cmd_Argc())
  1167.     {
  1168.         if (!strrchr(Cmd_Argv(i), '.'))
  1169.         {
  1170.             strcpy(name, Cmd_Argv(i));
  1171.             strcat(name, ".wav");
  1172.         }
  1173.         else
  1174.             strcpy(name, Cmd_Argv(i));
  1175.         sfx = S_RegisterSound(name);
  1176.         S_StartSound(NULL, cl.playernum+1, 0, sfx, 1.0, 1.0, 0);
  1177.         i++;
  1178.     }
  1179. }
  1180.  
  1181. void S_SoundList(void)
  1182. {
  1183.     int        i;
  1184.     sfx_t    *sfx;
  1185.     sfxcache_t    *sc;
  1186.     int        size, total;
  1187.  
  1188.     total = 0;
  1189.     for (sfx=known_sfx, i=0 ; i<num_sfx ; i++, sfx++)
  1190.     {
  1191.         if (!sfx->registration_sequence)
  1192.             continue;
  1193.         sc = sfx->cache;
  1194.         if (sc)
  1195.         {
  1196.             size = sc->length*sc->width*(sc->stereo+1);
  1197.             total += size;
  1198.             if (sc->loopstart >= 0)
  1199.                 Com_Printf ("L");
  1200.             else
  1201.                 Com_Printf (" ");
  1202.             Com_Printf("(%2db) %6i : %s\n",sc->width*8,  size, sfx->name);
  1203.         }
  1204.         else
  1205.         {
  1206.             if (sfx->name[0] == '*')
  1207.                 Com_Printf("  placeholder : %s\n", sfx->name);
  1208.             else
  1209.                 Com_Printf("  not loaded  : %s\n", sfx->name);
  1210.         }
  1211.     }
  1212.     Com_Printf ("Total resident: %i\n", total);
  1213. }
  1214.  
  1215.